﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.IO;

namespace Barbar.MapReport.DataSource.Esri {
  public class EsriRegionGeometryProvider : RegionGeometryProvider {
    private string m_ShpPath;
    private string m_DbfPath;
    private string m_IdColumnName;

    private bool m_IsInitialized;
    private SortedList<string, EsriRawRegion> m_Regions = new SortedList<string, EsriRawRegion>();
    private SortedList<int, Polygon> m_Polygons = new SortedList<int, Polygon>();

    public void EnsureCache() {
      if (!m_IsInitialized) {
        foreach (EsriRawRegion region in EsriRegionProvider.GetRegions(m_DbfPath, m_IdColumnName, null)) {
          m_Regions.Add(region.Id, region);
        }
        using(FileStream stream = new FileStream(m_ShpPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
          ShpFile file = new ShpFile(stream);
          foreach (ShpRecord record in file.Records) {
            if (record.ShapeType == ShpShapeType.Polygon || record.ShapeType == ShpShapeType.Polyline) {
              ShpRecordPolygon recordPolygon = (ShpRecordPolygon)record.Content;
              Polygon polygon = recordPolygon.Polygon.ToPolygon();
              m_Polygons.Add(record.Index, polygon);
            }
          }
        }
        m_IsInitialized = true;
      }
    }


    public override void Initialize(string name, NameValueCollection config) {
      base.Initialize(name, config);
      if (config == null)
        throw new ArgumentNullException("config");

      m_ShpPath = config["shpPath"];
      if (String.IsNullOrEmpty(m_ShpPath))
        throw new DataSourceException("shpPath is not specified.");

      m_DbfPath = config["dbfPath"];
      if (String.IsNullOrEmpty(m_DbfPath))
        throw new DataSourceException("dbfPath is not specified.");

      m_IdColumnName = config["idColumnName"];
      if (String.IsNullOrEmpty(m_IdColumnName))
        throw new DataSourceException("idColumnName is not specified.");
    }

    public override bool ContainsRegionGeometry(string regionId, ZoomLevel zoomLevel) {
      EnsureCache();

      EsriRawRegion region;
      if (!m_Regions.TryGetValue(regionId, out region))
        return false;

      return m_Polygons.ContainsKey(region.Index);
    }

    public override Polygon GetRegionGeometry(string regionId, ZoomLevel zoomLevel) {
      EnsureCache();

      EsriRawRegion region;
      if (!m_Regions.TryGetValue(regionId, out region))
        return null;

      return m_Polygons[region.Index];
    }
  }
}
